/**
  * @File    :   opt3001.c
  * @Time    :   2020/04/21 22:15:22
  * @Author  :   huenrong
  */

#include "opt3001.h"
#include "../i2c/i2c.h"

const uint32_t g_lsb_size[16] = {
    1,
    2,
    4,
    8,
    16,
    32,
    64,
    128,
    256,
    512,
    1024,
    2048,
    4096,
    8192,
    16384,
    32768,
};

/**
  * @name   opt3001_config
  * @brief  opt3001寄存器配置
  * @param  fd: 设备文件描述符
  * @retval 成功: 返回0
            失败: 返回-1
  */
static int opt3001_config(const int fd)
{
    int ret = -1;
    uint8_t send_buf[3] = {0};

    send_buf[0] = 0xC4;
    send_buf[1] = 0x10;
    ret = i2c_write_data_sub(fd, OPT3001_I2C_ADDR, CONFIG, send_buf, 2);
    if (2 != ret)
    {
        printf("opt3001 config fail\n");

        return -1;
    }

    return 0;
}

/**
  * @name   opt3001_read_manufacturer_id
  * @brief  读取opt3001厂商ID(默认为0x5449)
  * @param  manufacturer_id: 读取到的厂商ID
  * @param  fd: 设备文件描述符
  * @retval 成功: 返回0
            失败: 返回-1
  */
static int opt3001_read_manufacturer_id(uint16_t *manufacturer_id, const int fd)
{
    int ret = -1;
    uint8_t read_data[3] = {0};

    ret = i2c_read_data_sub(read_data, fd, OPT3001_I2C_ADDR, MANUFACTURER_ID, 2);
    if (2 == ret)
    {
        *manufacturer_id = ((read_data[0] << 8) | read_data[1]);

        return 0;
    }

    return -1;
}

/**
  * @name   opt3001_read_device_id
  * @brief  读取opt3001设备ID(默认为0x3001)
  * @param  device_id: 读取到的设备ID
  * @param  fd: 设备文件描述符
  * @retval 成功: 返回0
            失败: 返回-1
  */
static int opt3001_read_device_id(uint16_t *device_id, const int fd)
{
    int ret = -1;
    uint8_t read_data[3] = {0};

    ret = i2c_read_data_sub(read_data, fd, OPT3001_I2C_ADDR, OPT3001_DEVICE_ID, 2);
    if (2 == ret)
    {
        *device_id = ((read_data[0] << 8) | read_data[1]);

        return 0;
    }

    return -1;
}

/**
  * @name   opt3001_init
  * @brief  opt3001初始化
  * @param  fd: 设备文件描述符
  * @retval 成功: 返回0
            失败: 返回-1
  */
int opt3001_init(const int fd)
{
    uint8_t ret = 1;
    uint16_t manufacturer_id = 0;
    uint16_t device_id = 0;

    // 配置并唤醒opt3001
    ret = opt3001_config(fd);
    if (0 != ret)
    {
        printf("opt3001 config fail\n");

        return -1;
    }
    usleep(5 * 1000);

    ret = opt3001_read_manufacturer_id(&manufacturer_id, fd);
    if (0 != ret)
    {
        printf("opt3001 read manufacturer id fail\n");

        return -1;
    }
    usleep(1 * 1000);

    ret = opt3001_read_device_id(&device_id, fd);
    if (0 != ret)
    {
        printf("opt3001 read device id fail\n");

        return -1;
    }

    printf("opt3001 manufacturer_id: [0x%04X]\n", manufacturer_id);
    printf("opt3001 device_id: [0x%04X]\n", device_id);

    // 如果读出来的ID都正确表示初始化成功
    if ((0x5449 == manufacturer_id) && (0x3001 == device_id))
    {
        return 0;
    }

    return -1;
}

/**
  * @name   opt3001_read_lux
  * @brief  opt3001读取光照强度值
  * @param  read_lux: 读取到的光照强度值((单位: 0.01 lx))
  * @param  fd: 设备文件描述符
  * @retval 成功: 返回0
            失败: 返回-1
  */
int opt3001_read_lux(uint32_t *read_lux, const int fd)
{
    int ret = -1;
    uint8_t read_data[3] = {0};
    uint16_t lux = 0;

    *read_lux = 0;

    ret = i2c_read_data_sub(read_data, fd, OPT3001_I2C_ADDR, RESULT, 2);
    if (2 != ret)
    {
        printf("opt3001 read lux fail\n");

        return -1;
    }

    lux = ((read_data[0] << 8) | read_data[1]);

    // 得到结果是真实值的100倍
    *read_lux = g_lsb_size[(lux & 0xF000) >> 12];
    *read_lux *= (lux & 0x0FFF);

    return 0;
}
